﻿using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MyWeb.ServiceBus.Extensions.Authentication;
using MyWeb.ServiceBus.Extensions.Db;
using MyWeb.ServiceBus.Extensions.Serialization;
using MyWeb.ServiceBus.Extensions.Swagger;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyWeb.ServiceBus.Extensions.Consul
{
    public static class ConsulRegister
    {

        /// <summary>
        /// Consul 启动服务
        /// </summary>
        /// <param name="services"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void AddConsul(this IServiceCollection services, IConfigurationRoot? config)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            services.AddHttpContextAccessor();

            var address = config.GetValue<string>("Consul:config:ServiceUrl");

            // 创建 Consul 客户端实例并注册为单例服务
            services.AddSingleton<IConsulClient>(sp => new ConsulClient(cfg =>
            {
                cfg.Address = new Uri(address); // Consul 服务的地址
            }));
        }

        public static void UseConsul(this IApplicationBuilder app, IServiceCollection services, IConfigurationRoot? config, string address)
        {
            // ...
            // 将 Web API 服务注册到 Consul

            ConsulConfig consul = new ConsulConfig();
            config.Bind("Consul:config", consul);

            var serviceName = consul.ServiceName; // 服务名称
            var serviceId = consul.ServiceId;  // 服务ID

            var consulClient = services.BuildServiceProvider().GetService<IConsulClient>();
            var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

            // 获取当前 Web API 的地址和端口
            //var address = $"{Environment.GetEnvironmentVariable("ASPNETCORE_URLS")}/";
            var urls = address.Split(";");
            string url;
            if(urls.Count() > 1)
            {
                url = $"{urls[1]}/";
            }
            else { url = $"{urls[0]}/"; }
            // 创建 Consul 服务注册对象
            var registration = new AgentServiceRegistration()
            {
                ID = serviceId,
                Name = serviceName,
                Address = new Uri(url).Host,//这里只能使用主机名，不能包含端口，不然服务发现时可能报错
                Port = new Uri(url).Port,
                Tags = consul.Tags,
                Check = new AgentServiceCheck
                {
                    HTTP = $"{url}{consul.Heartbeat}",
                    Interval = TimeSpan.FromSeconds(consul.Interval),
                    Timeout = TimeSpan.FromSeconds(consul.Timeout),
                    //DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1)
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(consul.ServiceAfter)
                }
            };

            // 注册服务到 Consul
            consulClient.Agent.ServiceRegister(registration).ConfigureAwait(false).GetAwaiter().GetResult();

            // 应用程序停止时注销服务
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(serviceId).ConfigureAwait(false).GetAwaiter().GetResult();
            });
            // ...
        }
    }

    public class ConsulConfig
    {
        /// <summary>
        /// Consul服务地址
        /// </summary>
        public string ServiceUrl { get; set; } = string.Empty;
        /// <summary>
        /// 注册服务名称
        /// </summary>
        public string ServiceName { get; set; } = string.Empty;
        /// <summary>
        /// 注册服务Id
        /// </summary>
        public string ServiceId { get; set; } = string.Empty;
        /// <summary>
        /// 心跳检测
        /// </summary>
        public string Heartbeat { get; set; } = string.Empty;
        /// <summary>
        /// 标签
        /// </summary>
        public string[]? Tags { get; set; }
        /// <summary>
        /// 健康检查间隔（秒）
        /// </summary>
        public int Interval { get; set; } = 10;
        /// <summary>
        /// 健康检查超时（秒）
        /// </summary>
        public int Timeout { get; set; } = 5;
        /// <summary>
        /// 用于定义临时服务在不健康状态下的注销时间（秒）。
        /// 当一个服务在注册到 Consul 后，如果 Consul 在一段时间内无法检测到该服务的健康状态（即服务未能提供正常响应）
        /// 就会将该服务标记为不健康状态。
        /// 默认60
        /// </summary>
        public int ServiceAfter { get; set; } = 60;
    }
}
